﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Game
{
    public class GameApplication : Application
    {
        protected IDK.Engine Engine
        {
            get;
            set;
        }

        private StateManager mStateManager = null;
        private DataBase.Manager mDBManager = null;
        private CommonAction.ActionManager mActionManager = new CommonAction.ActionManager();

        public GameApplication()
        {
            Log.Hint("Game create");
        }

        protected override void OnCreate()
        {
            Engine = new IDK.Engine();
            Engine.Init();

            IDK.Viewport viewport = Engine.GetRenderer().CreateViewport((uint)WindowParam.Width, (uint)WindowParam.Height, Handle);
            Engine.GetRenderer().SetViewport(viewport);
            viewport = null;

            Engine.Start();

            mStateManager = new StateManager();

            //Set default path
            String rootPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\Resources\");
            Engine.GetCore().SetDefaultResourcePath(rootPath);

            mDBManager = new DataBase.Manager(rootPath + @"\db\global.s3db");

            GC.Collect();
            GC.WaitForPendingFinalizers();
            Log.Warn("Managed total memory using :" + GC.GetTotalMemory(true).ToString());

            Game.GameScene scene = new Game.GameScene(Engine);
            scene.ActionManager = mActionManager;

            GameLoadingState loadingState = new GameLoadingState(mDBManager);
            loadingState.GameScene = scene;

            GameState gameState = new GameState(mDBManager);
            gameState.GameScene = scene;

            UnloadingState unloadingState = new UnloadingState(mDBManager);
            unloadingState.GameScene = scene;

            mStateManager.Clear();
            mStateManager.Add(loadingState, gameState);
            mStateManager.Add(gameState, unloadingState);
            mStateManager.Add(unloadingState, null);

            mStateManager.SetState(loadingState);
        }

        protected override bool OnUpdate(Events.ProcessUpdate evnt)
        {
            Engine.Update(evnt.ElapsedTime);

            if (!mStateManager.Update(evnt))
            {
                return false;
            }

            return base.OnUpdate(evnt);
        }

        protected void CleanUp()
        {
            mActionManager = null;
            mStateManager = null; // release
            mDBManager = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        protected override void OnDestory()
        {
            CleanUp();

            //detach viewport
            Engine.GetRenderer().SetViewport(null);
            Engine.Stop();

            Engine = null;

            base.OnDestory();
        }


        protected override void OnActive(bool value)
        {
            Engine.Active(value);
            if (value == false)
            {
                Engine.Lock(true);
            }
            else
            {
                Engine.Unlock();
            }
        }

        public override void OnKeyDown(Events.UserInput input)
        {
            mActionManager.InputSubscriber.OnKeyDown(input);
        }

        public override void OnKeyUp(Events.UserInput input)
        {
            switch (input.Code)
            {
                //case Events.UserInput.Key.Esc:
               //     Terminated();
                //    break;

                default:
                    mActionManager.InputSubscriber.OnKeyUp(input);
                    break;
            }
        }

        public override void OnMouseMove(Events.MouseUserInput input)
        {
            mActionManager.InputSubscriber.OnMouseMove(input);
        }
        public override void OnMouseDown(Events.MouseUserInput input)
        {
            mActionManager.InputSubscriber.OnMouseDown(input);
        }
        public override void OnMouseUp(Events.MouseUserInput input)
        {
            mActionManager.InputSubscriber.OnMouseUp(input);
        }
    }
}
